feat: task-aware model routing via x-char-task header#4145
Conversation
Introduces a `CharTask` enum (chat/enhance/title) that flows from the frontend through a custom HTTP header to the LLM proxy, enabling task-specific model selection instead of a single model list for all requests. Refactors model resolution behind a `ModelResolver` trait with a `StaticModelResolver` implementation. Co-authored-by: Cursor <cursoragent@cursor.com>
✅ Deploy Preview for hyprnote canceled.
|
✅ Deploy Preview for hyprnote-storybook canceled.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
|
|
||
| Self { models } | ||
| } | ||
| } |
There was a problem hiding this comment.
Enhance task silently falls back to default models
Low Severity
StaticModelResolver::default() configures dedicated model pools for Chat and Title tasks but not Enhance, even though the frontend sends x-char-task: enhance on all enhance requests. The resolve method finds no "enhance" key and silently falls back to MODEL_KEY_DEFAULT, making the enhance task header a no-op for model selection. The test for this path is named unknown_task_falls_back_to_default, reinforcing that Enhance is treated the same as an unrecognized task despite being a first-class CharTask variant.


Summary
CharTaskenum (chat/enhance/title) that the frontend sends as anx-char-taskHTTP header on every LLM requestLlmProxyConfigmodel lists into aModelResolvertrait with aStaticModelResolverimplementation, so different tasks can map to different model poolsuseLanguageModel()call-sites to pass the appropriate task, and addscreateTracedFetch(task)to inject the header transparentlyTest plan
enhancetask modelschattask modelstitletask modelscargo test -p llm-proxypasses (unit tests forStaticModelResolver)Made with Cursor